<!DOCTYPE HTML>
<html lang="zh-CN">
<head><meta name="generator" content="Hexo 3.9.0">
    <!--Setting-->
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1">
    <meta http-equiv="Cache-Control" content="no-siteapp">
    <meta http-equiv="Cache-Control" content="no-transform">
    <meta name="renderer" content="webkit|ie-comp|ie-stand">
    <meta name="apple-mobile-web-app-capable" content="武威涛哥的博客">
    <meta name="apple-mobile-web-app-status-bar-style" content="black">
    <meta name="format-detection" content="telephone=no,email=no,adress=no">
    <meta name="browsermode" content="application">
    <meta name="screen-orientation" content="portrait">
    <meta name="theme-version" content="1.2.3">
    <meta name="root" content="/">
    <link rel="dns-prefetch" href="https://jaredtao.github.io">
    <!--SEO-->

    <meta name="keywords" content="Qt,Qt实用技能,QtCreator">


    <meta name="description" content="
简介
qmake简介
添加第三方库
示例1 - 直接链接库的全路径
示例2 - 路径中包含空格等特殊字符，用引号括起来。
示例3 - 分别指定路径和库
示例4 - 分平台条件链接
原理


影...">



<meta name="robots" content="all">
<meta name="google" content="all">
<meta name="googlebot" content="all">
<meta name="verify" content="all">

    <!--Title-->

<title>
    
    Qt实用技能2-用好qmake |
    
    武威涛哥的博客
</title>

    <link rel="alternate" href="/atom.xml" title="武威涛哥的博客" type="application/atom+xml">


    <link rel="icon" href="/favicon.ico">

    



<link rel="stylesheet" href="/css/bootstrap.min.css?rev=3.3.7">
<link rel="stylesheet" href="/css/font-awesome.min.css?rev=4.7.0">
<link rel="stylesheet" href="/css/style.css?rev=@@hash">




    
	<div class="hide">
		<script type="text/javascript">
			var cnzz_protocol = (("https:" == document.location.protocol) ? " https://" : " http://");document.write(unescape("%3Cspan class='cnzz_stat_icon_1263868967 hide' %3E%3Cscript%20src%3D%22https%3A%2F%2Fs95.cnzz.com%2Fz_stat.php%3Fweb_id%3D1272564536%22%3E%3C%2Fscript%3E%3C/span%3E%3Cscript src='" + cnzz_protocol + "s19.cnzz.com/z_stat.php%3Fid%3D1263868967%26show%3Dpic1' type='text/javascript'%3E%3C/script%3E"));
		</script>
	</div>






    

    <script>
        (function(){
            var bp = document.createElement('script');
            var curProtocol = window.location.protocol.split(':')[0];
            if (curProtocol === 'https') {
                bp.src = 'https://zz.bdstatic.com/linksubmit/push.js';
            }
            else {
                bp.src = 'http://push.zhanzhang.baidu.com/push.js';
            }
            var s = document.getElementsByTagName("script")[0];
            s.parentNode.insertBefore(bp, s);
        })();
    </script>

</head>

</html>
<!--[if lte IE 8]>
<style>
    html{ font-size: 1em }
</style>
<![endif]-->
<!--[if lte IE 9]>
<div style="ie">你使用的浏览器版本过低，为了你更好的阅读体验，请更新浏览器的版本或者使用其他现代浏览器，比如Chrome、Firefox、Safari等。</div>
<![endif]-->

<body>
    <header class="main-header"  style="background-image:url(http://snippet.shenliyang.com/img/banner.jpg)"  >
    <div class="main-header-box">
        <a class="header-avatar" href="/" title='JaredTao'>
            <img src="/img/avatar.jpg" alt="logo头像" class="img-responsive center-block">
        </a>
        <div class="branding">
        	<!--<h2 class="text-hide">Snippet主题,从未如此简单有趣</h2>-->
            
                <h2> 传承工匠精神 </h2>
            
    	</div>
    </div>
</header>
    <nav class="main-navigation">
    <div class="container">
        <div class="row">
            <div class="col-sm-12">
                <div class="navbar-header"><span class="nav-toggle-button collapsed pull-right" data-toggle="collapse" data-target="#main-menu" id="mnav">
                    <span class="sr-only"></span>
                        <i class="fa fa-bars"></i>
                    </span>
                    <a class="navbar-brand" href="https://jaredtao.github.io">武威涛哥的博客</a>
                </div>
                <div class="collapse navbar-collapse" id="main-menu">
                    <ul class="menu">
                        
                            <li role="presentation" class="text-center">
                                <a href="/"><i class="fa "></i>首页</a>
                            </li>
                        
                            <li role="presentation" class="text-center">
                                <a href="/categories/Qml组件化编程/"><i class="fa "></i>Qml组件化编程</a>
                            </li>
                        
                            <li role="presentation" class="text-center">
                                <a href="/categories/Qml特效/"><i class="fa "></i>Qml特效</a>
                            </li>
                        
                            <li role="presentation" class="text-center">
                                <a href="/categories/Qt进阶之路/"><i class="fa "></i>Qt进阶之路</a>
                            </li>
                        
                            <li role="presentation" class="text-center">
                                <a href="/categories/C-修炼之路/"><i class="fa "></i>C++修炼之路</a>
                            </li>
                        
                            <li role="presentation" class="text-center">
                                <a href="/categories/武威故事/"><i class="fa "></i>武威故事</a>
                            </li>
                        
                            <li role="presentation" class="text-center">
                                <a href="/archives/"><i class="fa "></i>时间轴</a>
                            </li>
                        
                    </ul>
                </div>
            </div>
        </div>
    </div>
</nav>
    <section class="content-wrap">
        <div class="container">
            <div class="row">
                <main class="col-md-8 main-content m-post">
                    <p id="process"></p>
<article class="post">
    <div class="post-head">
        <h1 id="Qt实用技能2-用好qmake">
            
	            Qt实用技能2-用好qmake
            
        </h1>
        <div class="post-meta">
    
        <span class="categories-meta fa-wrap">
            <i class="fa fa-folder-open-o"></i>
            <a class="category-link" href="/categories/Qt进阶之路/">Qt进阶之路</a>
        </span>
    

    
        <span class="fa-wrap">
            <i class="fa fa-tags"></i>
            <span class="tags-meta">
                
                    <a class="tag-link" href="/tags/Qt/">Qt</a> <a class="tag-link" href="/tags/QtCreator/">QtCreator</a> <a class="tag-link" href="/tags/Qt实用技能/">Qt实用技能</a>
                
            </span>
        </span>
    

    
        
        <span class="fa-wrap">
            <i class="fa fa-clock-o"></i>
            <span class="date-meta">2019/05/29</span>
        </span>
        
            <span class="fa-wrap">
                <i class="fa fa-eye"></i>
                <span id="busuanzi_value_page_pv"></span>
            </span>
        
    
</div>
            
            
    </div>
    
    <div id="post-gallery">
        
          <img src="/img/avatar.jpg" alt="gallery-img" class="gallery">
        
    </div>

    <div class="post-body post-content">
        <ul>
<li><a href="#%E7%AE%80%E4%BB%8B">简介</a></li>
<li><a href="#qmake%E7%AE%80%E4%BB%8B">qmake简介</a></li>
<li><a href="#%E6%B7%BB%E5%8A%A0%E7%AC%AC%E4%B8%89%E6%96%B9%E5%BA%93">添加第三方库</a><ul>
<li><a href="#%E7%A4%BA%E4%BE%8B1---%E7%9B%B4%E6%8E%A5%E9%93%BE%E6%8E%A5%E5%BA%93%E7%9A%84%E5%85%A8%E8%B7%AF%E5%BE%84">示例1 - 直接链接库的全路径</a></li>
<li><a href="#%E7%A4%BA%E4%BE%8B2---%E8%B7%AF%E5%BE%84%E4%B8%AD%E5%8C%85%E5%90%AB%E7%A9%BA%E6%A0%BC%E7%AD%89%E7%89%B9%E6%AE%8A%E5%AD%97%E7%AC%A6%E7%94%A8%E5%BC%95%E5%8F%B7%E6%8B%AC%E8%B5%B7%E6%9D%A5">示例2 - 路径中包含空格等特殊字符，用引号括起来。</a></li>
<li><a href="#%E7%A4%BA%E4%BE%8B3---%E5%88%86%E5%88%AB%E6%8C%87%E5%AE%9A%E8%B7%AF%E5%BE%84%E5%92%8C%E5%BA%93">示例3 - 分别指定路径和库</a></li>
<li><a href="#%E7%A4%BA%E4%BE%8B4---%E5%88%86%E5%B9%B3%E5%8F%B0%E6%9D%A1%E4%BB%B6%E9%93%BE%E6%8E%A5">示例4 - 分平台条件链接</a></li>
<li><a href="#%E5%8E%9F%E7%90%86">原理</a></li>
</ul>
</li>
<li><a href="#%E5%BD%B1%E5%AD%90%E6%9E%84%E5%BB%BA">影子构建</a><ul>
<li><a href="#%E6%8C%87%E5%AE%9A%E7%9B%AE%E6%A0%87%E8%B7%AF%E5%BE%84">指定目标路径</a></li>
<li><a href="#%E6%8C%87%E5%AE%9A%E4%B8%AD%E9%97%B4%E4%BB%B6%E7%94%9F%E6%88%90%E8%B7%AF%E5%BE%84">指定中间件生成路径</a></li>
</ul>
</li>
<li><a href="#%E6%8B%B7%E8%B4%9D%E8%B5%84%E6%BA%90">拷贝资源</a><ul>
<li><a href="#%E6%8B%B7%E8%B4%9D%E8%B5%84%E6%BA%90%E7%A4%BA%E4%BE%8B">拷贝资源示例</a></li>
<li><a href="#%E7%BC%96%E8%AF%91%E5%89%8D%E6%8B%B7%E8%B4%9D">编译前拷贝</a></li>
</ul>
</li>
<li><a href="#%E5%AE%89%E8%A3%85">安装</a></li>
<li><a href="#%E7%BB%93%E6%9D%9F%E8%AF%AD">结束语</a></li>
</ul>
<h2 id="简介"><a href="#简介" class="headerlink" title="简介"></a>简介</h2><p>本文是《Qt实用技能》系列文章的第二篇，涛哥将教大家，一些qmake的实用技巧。部分地方也会说一下原理，让大家知其然，知其所以然。</p>
<p>工欲善其事，必先利其器。</p>
<p>这个系列，全是干货！</p>
<p>注：文章主要发布在<a href="https://jaredtao.github.io">涛哥的博客</a> 和 <a href="https://zhuanlan.zhihu.com/TaoQt" target="_blank" rel="noopener">涛哥的知乎专栏-Qt进阶之路</a></p>
<h2 id="qmake简介"><a href="#qmake简介" class="headerlink" title="qmake简介"></a>qmake简介</h2><p>qmake是Qt的构建工具，主要作用是解析pro格式的项目文件、生成编译规则(Makefiles或其它)。</p>
<p>qmake是一个比较古老的工具，很多功能使用perl脚本实现，涛哥在其它地方就没怎么见过使用perl脚本的代码/项目。</p>
<p>Qt官方之前开发的Qbs，后来又宣布不再更新，现在又大力支持CMake。。。</p>
<p>在这样的背景下，qmake依然是当下主要的构建工具，所以qmake的一些技巧还是有必要掌握的。</p>
<p>qmake本身作为一个可执行程序，也是有一些参数的，但这不是本文的重点，本文的重点都在pro文件里。</p>
<p>pro文件中，除了常规的组织项目结构外，还可以做很多事情, 比如 指定编译选项、链接选项、制定目标生成规则、扩展编译规则 等等。</p>
<p>pro文件中的qmake语法，包括 变量声明和使用、内建变量、替换函数、测试函数等，帮助文档都有详细的介绍。</p>
<p>搜索关键词为qmake， 或者和普通的类查看帮助文档方式一样，光标放在pro文件要查看的变量上，按F1就能看到相应的说明。</p>
<p><img src="/images/Qt2/3.gif" alt="预览"></p>
<p>涛哥就不赘述了，后面用到的会单独说明。</p>
<h2 id="添加第三方库"><a href="#添加第三方库" class="headerlink" title="添加第三方库"></a>添加第三方库</h2><p>c++开发，使用第三方库也是家常便饭了，这是一个必备的技能。</p>
<p>这里首选的方法，是使用QtCreator提供的添加库UI。在pro文件里(或者项目文件夹), 鼠标右键-&gt;添加库，然后根据自己的需要下一步、下一步点一下即可。</p>
<p><img src="/images/Qt2/1.gif" alt="预览"></p>
<p>熟练的人也可以直接按pro语法(perl语法)写，给LIBS变量赋值。</p>
<p>下面给几个示例，至于动态库/静态库的差异，大家自己实践吧。</p>
<h3 id="示例1-直接链接库的全路径"><a href="#示例1-直接链接库的全路径" class="headerlink" title="示例1 - 直接链接库的全路径"></a>示例1 - 直接链接库的全路径</h3><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">LIBS += c:/mylibs/math.lib</span><br></pre></td></tr></table></figure>

<p>我们都知道windows系统默认的路径分割符是’&#39;，但在qmake中要写成’\‘才行。qmake也支持写成’/‘，其它unix系统又都是’/‘，</p>
<p>所以干脆都写成’/‘，方便处理。</p>
<h3 id="示例2-路径中包含空格等特殊字符，用引号括起来。"><a href="#示例2-路径中包含空格等特殊字符，用引号括起来。" class="headerlink" title="示例2 - 路径中包含空格等特殊字符，用引号括起来。"></a>示例2 - 路径中包含空格等特殊字符，用引号括起来。</h3><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">LIBS += "C:/mylibs/extra libs/extra.lib"</span><br></pre></td></tr></table></figure>

<h3 id="示例3-分别指定路径和库"><a href="#示例3-分别指定路径和库" class="headerlink" title="示例3 - 分别指定路径和库"></a>示例3 - 分别指定路径和库</h3><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">LIBS += "C:/mylibs/extra libs" -lextra</span><br></pre></td></tr></table></figure>

<p>这里的LIBS指定要链接的库，’-L’是指定链接库的路径，’-l’指定要链接的库名称</p>
<p>名称可以省略lib前缀和 扩展名后缀，Qt会自动处理。 后缀包括 ‘.so’ ‘.dll’ ‘.dylib’ 等。</p>
<h3 id="示例4-分平台条件链接"><a href="#示例4-分平台条件链接" class="headerlink" title="示例4 - 分平台条件链接"></a>示例4 - 分平台条件链接</h3><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">win32:LIBS += "C:/mylibs/extra libs/extra.lib"</span><br><span class="line">unix:LIBS += "-L/home/user/extra libs" -lextra</span><br></pre></td></tr></table></figure>

<p>条件链接可以很方便地实现不同平台链接不同的库。</p>
<p>这里的 win32 unix 是在选择了不同的编译器环境时，qmake分别预置的变量。</p>
<p>(比如win32平台相关的变量，可以参考msvc的配置文件:  [QTDIR]/mkspecs/win32-msvc/qmake.conf 和 [QTDIR]/mkspecs/common/msvc-desktop.conf)</p>
<h3 id="原理"><a href="#原理" class="headerlink" title="原理"></a>原理</h3><p>Qt内置了一些perl脚本，在执行qmake解析时会包含这些脚本。其中一些脚本会来处理这个LIBS变量，将其转换成编译器/链接器的参数。</p>
<p>内置的脚本路径在[QTDIR]/mkspecs/features文件夹下，扩展名为prf。</p>
<p><img src="/images/Qt2/2.png" alt="预览"></p>
<p>后续的很多变量，也是一样的原理, 只是处理方式各不相同。</p>
<p>很多pro文件的语法、功能实现，都可以参考这些prf来实现。</p>
<p>(注意：不熟悉的同学，不要乱改prf，容易改坏)</p>
<p>Qt程序员都知道的一件事：有时候修改了信号/槽相关的代码，不能正常运行，要重新qmake一下，才会生效。</p>
<p>本质上就是在重新触发[QTDIR]/mkspecs/features/moc.prf这个脚本。</p>
<p>(多少年了，都没有修好Moc生成问题，可见qmake的古老…)</p>
<h2 id="影子构建"><a href="#影子构建" class="headerlink" title="影子构建"></a>影子构建</h2><p>影子构建，就是编译生成的产物和源代码在不同的文件夹。这样可以防止源代码文件夹被污染。</p>
<p>QtCreator默认导入pro工程时，就会生成一个影子构建路径。比如这样：</p>
<p><img src="/images/Qt2/4.png" alt="预览"></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">F:\Dev\Qt\build-HelloTaoQuick-Desktop_Qt_5_12_3_MSVC2017_64bit-Debug</span><br></pre></td></tr></table></figure>

<p>之后编译项目时生成的中间文件及目标文件，都在这个文件夹中。</p>
<p>这个路径很长，而且编译器或者编译选项不同时都有可能不一样。</p>
<p>有时候要做一些特定的操作 比如目标exe生成到特定目录、拷贝资源文件等等，直接用这个路径会不太方便/不太可靠，我们需要一些定制。</p>
<h3 id="指定目标路径"><a href="#指定目标路径" class="headerlink" title="指定目标路径"></a>指定目标路径</h3><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">DESTDIR = $$PWD/bin</span><br></pre></td></tr></table></figure>

<p>通过给DESTDIR变量赋值， 可以指定生成的lib/exe放在哪个目录下</p>
<p>‘PWD’是qmake内置变量，’$$’是内置变量取值的写法。’/bin’是字符串拼接在变量后面。</p>
<p>更多内置变量可以参考qmake帮助文档，以及这篇文档<a href="https://wiki.qt.io/Undocumented_QMake" target="_blank" rel="noopener">隐藏的qmake文档</a></p>
<p>当然也可以参考那一堆prf和conf文件。</p>
<h3 id="指定中间件生成路径"><a href="#指定中间件生成路径" class="headerlink" title="指定中间件生成路径"></a>指定中间件生成路径</h3><p>可以通过这几个变量指定中间件生成的路径</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">config(debug, debug|release) &#123;</span><br><span class="line">    OBJECTS_DIR = build/debug/obj</span><br><span class="line">    MOC_DIR = build/debug/moc</span><br><span class="line">    RCC_DIR = build/debug/rcc</span><br><span class="line">    UI_DIR = build/debug/uic</span><br><span class="line">&#125; else &#123;</span><br><span class="line">    OBJECTS_DIR = build/release/obj</span><br><span class="line">    MOC_DIR = build/release/moc</span><br><span class="line">    RCC_DIR = build/release/rcc</span><br><span class="line">    UI_DIR = build/release/uic</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>config(debug, debug|release) 是一个条件表达式，可以理解为 </p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">if (debug === true) &#123;</span><br><span class="line"></span><br><span class="line">&#125; else if (release == true) &#123;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>注意: 按照perl语法，那个左大括号’{‘不能换行,要和前面的表达式在同一行。(有人自作聪明换行，被坑了呢😄)</p>
<p>上面这种指定中间件路径的方式，在QtCreator中有默认路径所以没有太大意义，不过在命令行编译时这样写却很有用。</p>
<h2 id="拷贝资源"><a href="#拷贝资源" class="headerlink" title="拷贝资源"></a>拷贝资源</h2><p>pro可以实现，在编译代码时，拷贝一些文件到指定的路径下</p>
<h3 id="拷贝资源示例"><a href="#拷贝资源示例" class="headerlink" title="拷贝资源示例"></a>拷贝资源示例</h3><p>这里以TaoQuick为例,来说明：</p>
<p>我在TaoQuick库目录下，有个叫qmldir的文件，需要在编译代码时自动拷贝到bin目录下。(先别管这个文件干嘛的，下一篇文章会说)</p>
<p><img src="/images/Qt2/5.png" alt="预览"></p>
<p>关键目录结构如下：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">TaoQuick</span><br><span class="line">    TaoQuick.pro</span><br><span class="line">    - bin</span><br><span class="line">        -TaoQuick</span><br><span class="line">    - TaoQuickCore</span><br><span class="line">        TaoQuickCore.pro</span><br><span class="line">        - Qml</span><br><span class="line">            qmldir</span><br></pre></td></tr></table></figure>

<p>那么我在TaoQuickCore.pro文件中的写法如下：</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">!equals(_PRO_FILE_PWD_, $$DESTDIR) &#123;</span><br><span class="line">    copy_qmldir.target = $$DESTDIR/qmldir</span><br><span class="line">    copy_qmldir.depends = $$_PRO_FILE_PWD_/qmldir</span><br><span class="line">    win32 &#123;</span><br><span class="line">        copy_qmldir.target ~= s,/,\\\\,g</span><br><span class="line">        copy_qmldir.depends ~= s,/,\\\\,g</span><br><span class="line">    &#125;</span><br><span class="line">    copy_qmldir.commands = $$&#123;QMAKE_COPY_FILE&#125; $$&#123;copy_qmldir.depends&#125; $$&#123;copy_qmldir.target&#125;</span><br><span class="line">    QMAKE_EXTRA_TARGETS += copy_qmldir</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>‘!equals(<em>PRO_FILE_PWD</em>, $$DESTDIR)’ 这一句是执行条件，即: 目标路径不等于pro文件所在路径时 执行下面的操作。</p>
<p>剩下的事情就是在创建一个”编译目标”（Target），将这个编译目标添加到QMAKE_EXTRA_TARGETS变量中就行了。</p>
<p>熟悉MakeFiles的同学应该都清楚什么是”目标”。不懂MakeFiles也没关系，这里的目标就理解为自己声明的一个变量即可。</p>
<p>这个变量有三个很重要的”子变量”:</p>
<p>copy_qmldir.target 指定目标文件所在的路径   (这里理解成要拷贝到哪去)<br>copy_qmldir.depends 指定依赖文件所在的路径  (这里理解成从哪里拷贝)<br>copy_qmldir.commands 指定拷贝操作的执行命令 (就是怎么拷贝)</p>
<p>QMAKE_COPY_FILE 这个变量来自前面说过的<a href="https://wiki.qt.io/Undocumented_QMake" target="_blank" rel="noopener">隐藏的qmake文档</a></p>
<p>qmake会在解析pro文件时，自动替换成平台相应的拷贝命令。 windows 平台就是 copy /y</p>
<p>注意windows的copy指令，路径分隔符得写成 ‘\‘才行。所以有了下面的特殊处理：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">win32 &#123;</span><br><span class="line">    copy_qmldir.target ~= s,/,\\\\,g</span><br><span class="line">    copy_qmldir.depends ~= s,/,\\\\,g</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>‘s,/,\\,g’ 是一个正则表达式，作用是把‘/’替换成‘\’ 。s表示开头，g表示结尾。</p>
<p>VAR~= REGEXP 是对变量VAR执行REGEXP这个正则表达式</p>
<h3 id="编译前拷贝"><a href="#编译前拷贝" class="headerlink" title="编译前拷贝"></a>编译前拷贝</h3><p>如果想在编译之前，先把资源拷贝完成，只需要前面的基础上，添加一句</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">PRE_TARGETDEPS += $$copy_qmldir.target</span><br></pre></td></tr></table></figure>

<p>也就是把”目标”加到 PRE_TARGETDEPS变量</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">!equals(_PRO_FILE_PWD_, $$DESTDIR) &#123;</span><br><span class="line">    copy_qmldir.target = $$DESTDIR/qmldir</span><br><span class="line">    copy_qmldir.depends = $$_PRO_FILE_PWD_/qmldir</span><br><span class="line">    win32 &#123;</span><br><span class="line">        copy_qmldir.target ~= s,/,\\\\,g</span><br><span class="line">        copy_qmldir.depends ~= s,/,\\\\,g</span><br><span class="line">    &#125;</span><br><span class="line">    copy_qmldir.commands = $$&#123;QMAKE_COPY_FILE&#125; $$&#123;copy_qmldir.depends&#125; $$&#123;copy_qmldir.target&#125;</span><br><span class="line">    QMAKE_EXTRA_TARGETS += copy_qmldir</span><br><span class="line">    PRE_TARGETDEPS += $$copy_qmldir.target</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h2 id="安装"><a href="#安装" class="headerlink" title="安装"></a>安装</h2><p>pro中还有一种INSTALL功能，可以执行文件拷贝。</p>
<p>和编译期拷贝 类似，INSTALL用起来更简单无脑一些，而且INSTALL只在执行make install指令时，才会拷贝资源。</p>
<p>还是以TaoQuick为例, 我有一堆文件，需要在make install时，安装到Qt的Qml路径中</p>
<p><img src="/images/Qt2/6.png" alt="预览"></p>
<p>如上图所示所有的文件, 除了TaoQuickDesigner.pri, 都要按照这个结构拷贝。</p>
<p>(这个pri文件是pro文件的一小部分，可以直接在pro中通过include引入。</p>
<p>pri和pro语法一样，但是qmake不直接识别pri，只识别pro</p>
<p>pri一般用来写一些公用的部分，让多个pro公用)</p>
<p>拷贝整个文件夹是一种做法, 当然为了精确地控制要拷贝的内容，可以写成下面这样：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line">taoquick_designer.files = $$PWD/designer/TaoQuick.metainfo</span><br><span class="line">taoquick_designer.path = $$[QT_INSTALL_QML]/$$&#123;uri&#125;/designer</span><br><span class="line"></span><br><span class="line">toaquick_qmldir.files = $$PWD/qmldir</span><br><span class="line">toaquick_qmldir.path = $$[QT_INSTALL_QML]/$$&#123;uri&#125;</span><br><span class="line"></span><br><span class="line">taoquick_qml_buttons.files = $$PWD/BasicComponent/Button/*.qml</span><br><span class="line">taoquick_qml_buttons.path = $$[QT_INSTALL_QML]/$$&#123;uri&#125;/BasicComponent/Button</span><br><span class="line"></span><br><span class="line">taoquick_qml_mouse.files = $$PWD/BasicComponent/Mouse/*.qml</span><br><span class="line">taoquick_qml_mouse.path = $$[QT_INSTALL_QML]/$$&#123;uri&#125;/BasicComponent/Mouse</span><br><span class="line"></span><br><span class="line">taoquick_qml_others.files = $$PWD/BasicComponent/Others/*.qml</span><br><span class="line">taoquick_qml_others.path = $$[QT_INSTALL_QML]/$$&#123;uri&#125;/BasicComponent/Others</span><br><span class="line"></span><br><span class="line">taoquick_qml_progress.files = $$PWD/BasicComponent/Progress/*.qml</span><br><span class="line">taoquick_qml_progress.path = $$[QT_INSTALL_QML]/$$&#123;uri&#125;/BasicComponent/Progress</span><br><span class="line"></span><br><span class="line">taoquick_degisner_images.files = $$PWD/designer/images/*.png</span><br><span class="line">taoquick_degisner_images.path = $$[QT_INSTALL_QML]/$$&#123;uri&#125;/designer/images</span><br><span class="line"></span><br><span class="line">INSTALLS  += taoquick_designer toaquick_qmldir taoquick_qml_buttons taoquick_qml_mouse taoquick_qml_others taoquick_qml_progress taoquick_degisner_images</span><br></pre></td></tr></table></figure>

<p>自定义一个变量，然后其子变量files指定要拷贝的文件，子变量path指定目标路径。</p>
<p>把自定义变量加入INSTALLS变量就行了。</p>
<p>QT_INSTALL_QML也是一个内置变量，默认值为[QTDIR]/qml。</p>
<p>之后只要执行以下命令，就能完成资源拷贝。</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">qmake</span><br><span class="line">make </span><br><span class="line">make install</span><br></pre></td></tr></table></figure>

<p>当然QtCreator中也能执行make install</p>
<p>如下图所示:</p>
<p><img src="/images/Qt2/QtCreator-install.png" alt="预览"></p>
<p>任意编译器kit都可以，项目-&gt;构建步骤-&gt;添加build步骤-&gt;Make，添加之后在make参数中输入install。最后重新构建工程，即可完成安装。</p>
<h2 id="结束语"><a href="#结束语" class="headerlink" title="结束语"></a>结束语</h2><p>以上案例，大部分都在TaoQuick项目中实践过，可以去Github参考。</p>
<p><a href="https://github.com/jaredtao/TaoQuick" target="_blank" rel="noopener">TaoQuick</a></p>

    </div>
    
        <div class="reward" ontouchstart>
    <div class="reward-wrap">赏
        <div class="reward-box">
            
                <span class="reward-type">
                    <img class="alipay" src="/img/zhifubao.jpg"><b>支付宝打赏</b>
                </span>
            
            
                <span class="reward-type">
                    <img class="wechat" src="/img/weixin.jpg"><b>微信打赏</b>
                </span>
            
        </div>
    </div>
    <p class="reward-tip">赞赏是不耍流氓的鼓励</p>
</div>


    
    <div class="post-footer">
        <div>
            
                转载声明：文章采用<a href="http://creativecommons.org/licenses/by-nc-sa/4.0/" target="_blank">知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议</a>进行许可, 转载请注明出处 © <a href="https://jaredtao.github.io" target="_blank">武威的涛哥</a>
            
        </div>
        <div>
            
        </div>
    </div>
</article>

<div class="article-nav prev-next-wrap clearfix">
    
        <a href="/2019/06/01/Qml组件化编程10-自定义Quick模块/" class="pre-post btn btn-default" title='Qml组件化编程10-自定义Quick模块'>
            <i class="fa fa-angle-left fa-fw"></i><span class="hidden-lg">上一篇</span>
            <span class="hidden-xs">Qml组件化编程10-自定义Quick模块</span>
        </a>
    
    
        <a href="/2019/05/24/Qml组件化编程9-Model和View/" class="next-post btn btn-default" title='Qml组件化编程9-Model和View'>
            <span class="hidden-lg">下一篇</span>
            <span class="hidden-xs">Qml组件化编程9-Model和View</span><i class="fa fa-angle-right fa-fw"></i>
        </a>
    
</div>


    <div id="comments">
        
	
    <div id="vcomments" class="valine"></div>
    <script src="//cdn1.lncld.net/static/js/3.0.4/av-min.js"></script>
<script src="/assets/valine.min.js"></script>

    <script>
        new Valine({
            av: AV,
            el: '#vcomments',
            appId: 'qegD4552u6FU9HoNDvRsonko-gzGzoHsz',
            appKey: 'eitB2FV5n2qyMHcDM7x6EQpt',
            placeholder: '说点什么吧',
            notify: false,
            verify: false,
            avatar: 'mm',
            meta: 'nick,mail'.split(','),
            pageSize: '10',
            path: window.location.pathname,
            lang: 'zh-CN'.toLowerCase()
        })
    </script>


    </div>





                </main>
                
                    <aside id="article-toc" role="navigation" class="col-md-4">
    <div class="widget">
        <h3 class="title">文章目录</h3>
        
            <ol class="toc"><li class="toc-item toc-level-2"><a class="toc-link" href="#简介"><span class="toc-text">简介</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#qmake简介"><span class="toc-text">qmake简介</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#添加第三方库"><span class="toc-text">添加第三方库</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#示例1-直接链接库的全路径"><span class="toc-text">示例1 - 直接链接库的全路径</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#示例2-路径中包含空格等特殊字符，用引号括起来。"><span class="toc-text">示例2 - 路径中包含空格等特殊字符，用引号括起来。</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#示例3-分别指定路径和库"><span class="toc-text">示例3 - 分别指定路径和库</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#示例4-分平台条件链接"><span class="toc-text">示例4 - 分平台条件链接</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#原理"><span class="toc-text">原理</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#影子构建"><span class="toc-text">影子构建</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#指定目标路径"><span class="toc-text">指定目标路径</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#指定中间件生成路径"><span class="toc-text">指定中间件生成路径</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#拷贝资源"><span class="toc-text">拷贝资源</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#拷贝资源示例"><span class="toc-text">拷贝资源示例</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#编译前拷贝"><span class="toc-text">编译前拷贝</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#安装"><span class="toc-text">安装</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#结束语"><span class="toc-text">结束语</span></a></li></ol>
        
    </div>
</aside>

                
            </div>
        </div>
    </section>
    <footer class="main-footer">
    <div class="container">
        <div class="row">
        </div>
    </div>
</footer>

<a id="back-to-top" class="icon-btn hide">
	<i class="fa fa-chevron-up"></i>
</a>




    <div class="copyright">
    <div class="container">
        <div class="row">
            <div class="col-sm-12">
                <div class="busuanzi">
    
        访问量:
        <strong id="busuanzi_value_site_pv">
            <i class="fa fa-spinner fa-spin"></i>
        </strong>
        &nbsp; | &nbsp;
        访客数:
        <strong id="busuanzi_value_site_uv">
            <i class="fa fa-spinner fa-spin"></i>
        </strong>
    
</div>

            </div>
            <div class="col-sm-12">
                <span>Copyright &copy;
                    2019
                    
                </span> |
                <span>
                    Powered by <a href="//hexo.io" class="copyright-links" target="_blank" rel="nofollow">Hexo</a>
                </span> |
                <span>
                    Theme by <a href="//github.com/shenliyang/hexo-theme-snippet.git" class="copyright-links" target="_blank" rel="nofollow">Snippet</a>
                </span>
            </div>
        </div>
    </div>
</div>




    <script src="/assets/tagcanvas.min.js?rev=2.9"></script>
    <script>
        var tagOption = {
            textColour: '#444', // 字体颜色
            outlineMethod: 'block', // 选中模式
            outlineColour: '#FFDAB9', // 选中模式的颜色
            interval: 30 || 30, // 动画帧之间的时间间隔，值越大，转动幅度越大
            textHeight: 13,
            outlineRadius: 3,
            freezeActive: true || '', // 选中的标签是否继续滚动
            frontSelect: true || '', // 不选标签云后部的标签
            initial: [0.1, -0.1],
            depth: 0.5,
            decel: 0.95,
            maxSpeed: 0.03,
            reverse: true || '', // 是否反向触发
            fadeIn: 500, // 进入动画时间
            wheelZoom: false || '' // 是否启用鼠标滚轮
        }
        TagCanvas.Start('tag-cloud-3d','',tagOption);
    </script>



    <script async src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script>


<script src="/js/app.js?rev=@@hash"></script>

</body>
</html>